package com.hsurosy.hsuchain.nft.user.infrastructure.mapper;

import com.hsurosy.hsuchain.nft.user.infrastructure.util.AesUtil;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * AES加密类型处理器
 *
 * @Author Hsu琛君珩
 * @Date 2024-10-05 18:16
 * @Description
 * @Version: v1.0.0
 */
public class AesEncryptTypeHandler extends BaseTypeHandler<String> {

    /**
     * 将非空的参数设置到PreparedStatement中，并在设置前进行加密操作
     *
     * @param ps PreparedStatement对象
     * @param i 参数索引
     * @param parameter 需要加密的参数
     * @param jdbcType JDBC类型
     * @throws SQLException 当SQL操作发生错误时抛出
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        // 对数据进行加密处理，然后设置到PreparedStatement中
        ps.setString(i, encrypt(parameter));
    }

    /**
     * 获取数据库结果集中的指定列的数据，并进行解密操作
     *
     * @param rs 结果集对象
     * @param columnName 列名称
     * @return 解密后的数据
     * @throws SQLException 当SQL操作发生错误时抛出
     */
    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String encrypted = rs.getString(columnName);  // 获取加密的字符串
        return encrypted == null ? null : decrypt(encrypted);  // 解密并返回结果
    }

    /**
     * 获取数据库结果集中指定索引的数据，并进行解密操作
     *
     * @param rs 结果集对象
     * @param columnIndex 列索引
     * @return 解密后的数据
     * @throws SQLException 当SQL操作发生错误时抛出
     */
    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String encrypted = rs.getString(columnIndex);  // 获取加密的字符串
        return encrypted == null ? null : decrypt(encrypted);  // 解密并返回结果
    }

    /**
     * 获取存储过程的结果集中指定索引的数据，并进行解密操作
     *
     * @param cs CallableStatement对象（存储过程调用）
     * @param columnIndex 列索引
     * @return 解密后的数据
     * @throws SQLException 当SQL操作发生错误时抛出
     */
    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String encrypted = cs.getString(columnIndex);  // 获取加密的字符串
        return encrypted == null ? null : decrypt(encrypted);  // 解密并返回结果
    }

    /**
     * 加密方法
     *
     * @param data 需要加密的原始字符串
     * @return 加密后的字符串
     */
    private String encrypt(String data) {
        // 调用AesUtil工具类进行AES加密
        return AesUtil.encrypt(data);
    }

    /**
     * 解密方法
     *
     * @param data 需要解密的加密字符串
     * @return 解密后的字符串
     */
    private String decrypt(String data) {
        // 调用AesUtil工具类进行AES解密
        return AesUtil.decrypt(data);
    }
}
